/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxEvent =
{

  /**
	 * Class: mxEvent
	 *
	 * Cross-browser DOM event support. For internal event handling,
	 * <mxEventSource> and the graph event dispatch loop in <mxGraph> are used.
	 *
	 * Memory Leaks:
	 *
	 * Use this class for adding and removing listeners to/from DOM nodes. The
	 * <removeAllListeners> function is provided to remove all listeners that
	 * have been added using <addListener>. The function should be invoked when
	 * the last reference is removed in the JavaScript code, typically when the
	 * referenced DOM node is removed from the DOM.
	 *
	 * Function: addListener
	 *
	 * Binds the function to the specified event on the given element. Use
	 * <mxUtils.bind> in order to bind the "this" keyword inside the function
	 * to a given execution scope.
	 */
  addListener: (function () {
    var updateListenerList = function (element, eventName, funct) {
      if (element.mxListenerList == null) {
        element.mxListenerList = []
      }

      var entry = { name: eventName, f: funct }
      element.mxListenerList.push(entry)
    }

    if (window.addEventListener) {
      return function (element, eventName, funct) {
        element.addEventListener(eventName, funct, false)
        updateListenerList(element, eventName, funct)
      }
    } else {
      return function (element, eventName, funct) {
        element.attachEvent('on' + eventName, funct)
        updateListenerList(element, eventName, funct)
      }
    }
  }()),

  /**
	 * Function: removeListener
	 *
	 * Removes the specified listener from the given element.
	 */
  removeListener: (function () {
    var updateListener = function (element, eventName, funct) {
      if (element.mxListenerList != null) {
        var listenerCount = element.mxListenerList.length

        for (var i = 0; i < listenerCount; i++) {
          var entry = element.mxListenerList[i]

          if (entry.f == funct) {
            element.mxListenerList.splice(i, 1)
            break
          }
        }

        if (element.mxListenerList.length == 0) {
          element.mxListenerList = null
        }
      }
    }

    if (window.removeEventListener) {
      return function (element, eventName, funct) {
        element.removeEventListener(eventName, funct, false)
        updateListener(element, eventName, funct)
      }
    } else {
      return function (element, eventName, funct) {
        element.detachEvent('on' + eventName, funct)
        updateListener(element, eventName, funct)
      }
    }
  }()),

  /**
	 * Function: removeAllListeners
	 *
	 * Removes all listeners from the given element.
	 */
  removeAllListeners: function (element) {
    var list = element.mxListenerList

    if (list != null) {
      while (list.length > 0) {
        var entry = list[0]
        mxEvent.removeListener(element, entry.name, entry.f)
      }
    }
  },

  /**
	 * Function: addGestureListeners
	 *
	 * Adds the given listeners for touch, mouse and/or pointer events. If
	 * <mxClient.IS_POINTER> is true then pointer events will be registered,
	 * else the respective mouse events will be registered. If <mxClient.IS_POINTER>
	 * is false and <mxClient.IS_TOUCH> is true then the respective touch events
	 * will be registered as well as the mouse events.
	 */
  addGestureListeners: function (node, startListener, moveListener, endListener) {
    if (startListener != null) {
      mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', startListener)
    }

    if (moveListener != null) {
      mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', moveListener)
    }

    if (endListener != null) {
      mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointerup' : 'mouseup', endListener)
    }

    if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {
      if (startListener != null) {
        mxEvent.addListener(node, 'touchstart', startListener)
      }

      if (moveListener != null) {
        mxEvent.addListener(node, 'touchmove', moveListener)
      }

      if (endListener != null) {
        mxEvent.addListener(node, 'touchend', endListener)
      }
    }
  },

  /**
	 * Function: removeGestureListeners
	 *
	 * Removes the given listeners from mousedown, mousemove, mouseup and the
	 * respective touch events if <mxClient.IS_TOUCH> is true.
	 */
  removeGestureListeners: function (node, startListener, moveListener, endListener) {
    if (startListener != null) {
      mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', startListener)
    }

    if (moveListener != null) {
      mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', moveListener)
    }

    if (endListener != null) {
      mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointerup' : 'mouseup', endListener)
    }

    if (!mxClient.IS_POINTER && mxClient.IS_TOUCH) {
      if (startListener != null) {
        mxEvent.removeListener(node, 'touchstart', startListener)
      }

      if (moveListener != null) {
        mxEvent.removeListener(node, 'touchmove', moveListener)
      }

      if (endListener != null) {
        mxEvent.removeListener(node, 'touchend', endListener)
      }
    }
  },

  /**
	 * Function: redirectMouseEvents
	 *
	 * Redirects the mouse events from the given DOM node to the graph dispatch
	 * loop using the event and given state as event arguments. State can
	 * either be an instance of <mxCellState> or a function that returns an
	 * <mxCellState>. The down, move, up and dblClick arguments are optional
	 * functions that take the trigger event as arguments and replace the
	 * default behaviour.
	 */
  redirectMouseEvents: function (node, graph, state, down, move, up, dblClick) {
    var getState = function (evt) {
      return (typeof (state) === 'function') ? state(evt) : state
    }

    mxEvent.addGestureListeners(node, function (evt) {
      if (down != null) {
        down(evt)
      } else if (!mxEvent.isConsumed(evt)) {
        graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt, getState(evt)))
      }
    },
    function (evt) {
      if (move != null) {
        move(evt)
      } else if (!mxEvent.isConsumed(evt)) {
        graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, getState(evt)))
      }
    },
    function (evt) {
      if (up != null) {
        up(evt)
      } else if (!mxEvent.isConsumed(evt)) {
        graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt, getState(evt)))
      }
    })

    mxEvent.addListener(node, 'dblclick', function (evt) {
      if (dblClick != null) {
        dblClick(evt)
      } else if (!mxEvent.isConsumed(evt)) {
        var tmp = getState(evt)
        graph.dblClick(evt, (tmp != null) ? tmp.cell : null)
      }
    })
  },

  /**
	 * Function: release
	 *
	 * Removes the known listeners from the given DOM node and its descendants.
	 *
	 * Parameters:
	 *
	 * element - DOM node to remove the listeners from.
	 */
  release: function (element) {
    try {
      if (element != null) {
        mxEvent.removeAllListeners(element)

        var children = element.childNodes

        if (children != null) {
			        var childCount = children.length

			        for (var i = 0; i < childCount; i += 1) {
			        	mxEvent.release(children[i])
			        }
			    }
      }
    } catch (e) {
      // ignores errors as this is typically called in cleanup code
    }
  },

  /**
	 * Function: addMouseWheelListener
	 *
	 * Installs the given function as a handler for mouse wheel events. The
	 * function has two arguments: the mouse event and a boolean that specifies
	 * if the wheel was moved up or down.
	 *
	 * This has been tested with IE 6 and 7, Firefox (all versions), Opera and
	 * Safari. It does currently not work on Safari for Mac.
	 *
	 * Example:
	 *
	 * (code)
	 * mxEvent.addMouseWheelListener(function (evt, up)
	 * {
	 *   mxLog.show();
	 *   mxLog.debug('mouseWheel: up='+up);
	 * });
	 *(end)
	 *
	 * Parameters:
	 *
	 * funct - Handler function that takes the event argument and a boolean up
	 * argument for the mousewheel direction.
	 * target - Target for installing the listener in Google Chrome. See
	 * https://www.chromestatus.com/features/6662647093133312.
	 */
  addMouseWheelListener: function (funct, target) {
    if (funct != null) {
      var wheelHandler = function (evt) {
        // IE does not give an event object but the
        // global event object is the mousewheel event
        // at this point in time.
        if (evt == null) {
          evt = window.event
        }

        // To prevent window zoom on trackpad pinch
        if (evt.ctrlKey) {
          evt.preventDefault()
        }

        var delta = -evt.deltaY

        // Handles the event using the given function
        if (Math.abs(evt.deltaX) > 0.5 || Math.abs(evt.deltaY) > 0.5) {
          funct(evt, (evt.deltaY == 0) ? -evt.deltaX > 0 : -evt.deltaY > 0)
        }
      }

      target = target != null ? target : window

      if (mxClient.IS_SF && !mxClient.IS_TOUCH) {
        var scale = 1

        mxEvent.addListener(target, 'gesturestart', function (evt) {
          mxEvent.consume(evt)
          scale = 1
        })

        mxEvent.addListener(target, 'gesturechange', function (evt) {
          mxEvent.consume(evt)
          var diff = scale - evt.scale

          if (Math.abs(diff) > 0.2) {
            funct(evt, diff < 0, true)
            scale = evt.scale
          }
        })

        mxEvent.addListener(target, 'gestureend', function (evt) {
          mxEvent.consume(evt)
        })
      }

      mxEvent.addListener(target, 'wheel', wheelHandler)
    }
  },

  /**
	 * Function: disableContextMenu
	 *
	 * Disables the context menu for the given element.
	 */
  disableContextMenu: function (element) {
    mxEvent.addListener(element, 'contextmenu', function (evt) {
      if (evt.preventDefault) {
        evt.preventDefault()
      }

      return false
    })
  },

  /**
	 * Function: getSource
	 *
	 * Returns the event's target or srcElement depending on the browser.
	 */
  getSource: function (evt) {
    return (evt.srcElement != null) ? evt.srcElement : evt.target
  },

  /**
	 * Function: isConsumed
	 *
	 * Returns true if the event has been consumed using <consume>.
	 */
  isConsumed: function (evt) {
    return evt.isConsumed != null && evt.isConsumed
  },

  /**
	 * Function: isTouchEvent
	 *
	 * Returns true if the event was generated using a touch device (not a pen or mouse).
	 */
  isTouchEvent: function (evt) {
    return (evt.pointerType != null) ? (evt.pointerType == 'touch' || evt.pointerType ===
			evt.MSPOINTER_TYPE_TOUCH) : ((evt.mozInputSource != null)
      ? evt.mozInputSource == 5 : evt.type.indexOf('touch') == 0)
  },

  /**
	 * Function: isPenEvent
	 *
	 * Returns true if the event was generated using a pen (not a touch device or mouse).
	 */
  isPenEvent: function (evt) {
    return (evt.pointerType != null) ? (evt.pointerType == 'pen' || evt.pointerType ===
			evt.MSPOINTER_TYPE_PEN) : ((evt.mozInputSource != null)
      ? evt.mozInputSource == 2 : evt.type.indexOf('pen') == 0)
  },

  /**
	 * Function: isMultiTouchEvent
	 *
	 * Returns true if the event was generated using a touch device (not a pen or mouse).
	 */
  isMultiTouchEvent: function (evt) {
    return (evt.type != null && evt.type.indexOf('touch') == 0 && evt.touches != null && evt.touches.length > 1)
  },

  /**
	 * Function: isMouseEvent
	 *
	 * Returns true if the event was generated using a mouse (not a pen or touch device).
	 */
  isMouseEvent: function (evt) {
    return (evt.pointerType != null) ? (evt.pointerType == 'mouse' || evt.pointerType ===
			evt.MSPOINTER_TYPE_MOUSE) : ((evt.mozInputSource != null)
      ? evt.mozInputSource == 1 : evt.type.indexOf('mouse') == 0)
  },

  /**
	 * Function: isLeftMouseButton
	 *
	 * Returns true if the left mouse button is pressed for the given event.
	 * To check if a button is pressed during a mouseMove you should use the
	 * <mxGraph.isMouseDown> property. Note that this returns true in Firefox
	 * for control+left-click on the Mac.
	 */
  isLeftMouseButton: function (evt) {
    // Special case for mousemove and mousedown we check the buttons
    // if it exists because which is 0 even if no button is pressed
    if ('buttons' in evt && (evt.type == 'mousedown' || evt.type == 'mousemove')) {
      return evt.buttons == 1
    } else if ('which' in evt) {
	        return evt.which === 1
	    } else {
	        return evt.button === 1
	    }
  },

  /**
	 * Function: isMiddleMouseButton
	 *
	 * Returns true if the middle mouse button is pressed for the given event.
	 * To check if a button is pressed during a mouseMove you should use the
	 * <mxGraph.isMouseDown> property.
	 */
  isMiddleMouseButton: function (evt) {
    if ('which' in evt) {
	        return evt.which === 2
	    } else {
	        return evt.button === 4
	    }
  },

  /**
	 * Function: isRightMouseButton
	 *
	 * Returns true if the right mouse button was pressed. Note that this
	 * button might not be available on some systems. For handling a popup
	 * trigger <isPopupTrigger> should be used.
	 */
  isRightMouseButton: function (evt) {
    if ('which' in evt) {
	        return evt.which === 3
	    } else {
	        return evt.button === 2
	    }
  },

  /**
	 * Function: isPopupTrigger
	 *
	 * Returns true if the event is a popup trigger. This implementation
	 * returns true if the right button or the left button and control was
	 * pressed on a Mac.
	 */
  isPopupTrigger: function (evt) {
    return mxEvent.isRightMouseButton(evt) || (mxClient.IS_MAC && mxEvent.isControlDown(evt) &&
			!mxEvent.isShiftDown(evt) && !mxEvent.isMetaDown(evt) && !mxEvent.isAltDown(evt))
  },

  /**
	 * Function: isShiftDown
	 *
	 * Returns true if the shift key is pressed for the given event.
	 */
  isShiftDown: function (evt) {
    return (evt != null) ? evt.shiftKey : false
  },

  /**
	 * Function: isAltDown
	 *
	 * Returns true if the alt key is pressed for the given event.
	 */
  isAltDown: function (evt) {
    return (evt != null) ? evt.altKey : false
  },

  /**
	 * Function: isControlDown
	 *
	 * Returns true if the control key is pressed for the given event.
	 */
  isControlDown: function (evt) {
    return (evt != null) ? evt.ctrlKey : false
  },

  /**
	 * Function: isMetaDown
	 *
	 * Returns true if the meta key is pressed for the given event.
	 */
  isMetaDown: function (evt) {
    return (evt != null) ? evt.metaKey : false
  },

  /**
	 * Function: getMainEvent
	 *
	 * Returns the touch or mouse event that contains the mouse coordinates.
	 */
  getMainEvent: function (e) {
    if ((e.type == 'touchstart' || e.type == 'touchmove') && e.touches != null && e.touches[0] != null) {
      e = e.touches[0]
    } else if (e.type == 'touchend' && e.changedTouches != null && e.changedTouches[0] != null) {
      e = e.changedTouches[0]
    }

    return e
  },

  /**
	 * Function: getClientX
	 *
	 * Returns true if the meta key is pressed for the given event.
	 */
  getClientX: function (e) {
    return mxEvent.getMainEvent(e).clientX
  },

  /**
	 * Function: getClientY
	 *
	 * Returns true if the meta key is pressed for the given event.
	 */
  getClientY: function (e) {
    return mxEvent.getMainEvent(e).clientY
  },

  /**
	 * Function: consume
	 *
	 * Consumes the given event.
	 *
	 * Parameters:
	 *
	 * evt - Native event to be consumed.
	 * preventDefault - Optional boolean to prevent the default for the event.
	 * Default is true.
	 * stopPropagation - Option boolean to stop event propagation. Default is
	 * true.
	 */
  consume: function (evt, preventDefault, stopPropagation) {
    preventDefault = (preventDefault != null) ? preventDefault : true
    stopPropagation = (stopPropagation != null) ? stopPropagation : true

    if (preventDefault) {
      if (evt.preventDefault) {
        if (stopPropagation) {
          evt.stopPropagation()
        }

        evt.preventDefault()
      } else if (stopPropagation) {
        evt.cancelBubble = true
      }
    }

    // Opera
    evt.isConsumed = true

    // Other browsers
    if (!evt.preventDefault) {
      evt.returnValue = false
    }
  },

  //
  // Special handles in mouse events
  //

  /**
	 * Variable: LABEL_HANDLE
	 *
	 * Index for the label handle in an mxMouseEvent. This should be a negative
	 * value that does not interfere with any possible handle indices. Default
	 * is -1.
	 */
  LABEL_HANDLE: -1,

  /**
	 * Variable: ROTATION_HANDLE
	 *
	 * Index for the rotation handle in an mxMouseEvent. This should be a
	 * negative value that does not interfere with any possible handle indices.
	 * Default is -2.
	 */
  ROTATION_HANDLE: -2,

  /**
	 * Variable: CUSTOM_HANDLE
	 *
	 * Start index for the custom handles in an mxMouseEvent. This should be a
	 * negative value and is the start index which is decremented for each
	 * custom handle. Default is -100.
	 */
  CUSTOM_HANDLE: -100,

  /**
	 * Variable: VIRTUAL_HANDLE
	 *
	 * Start index for the virtual handles in an mxMouseEvent. This should be a
	 * negative value and is the start index which is decremented for each
	 * virtual handle. Default is -100000. This assumes that there are no more
	 * than VIRTUAL_HANDLE - CUSTOM_HANDLE custom handles.
	 *
	 */
  VIRTUAL_HANDLE: -100000,

  //
  // Event names
  //

  /**
	 * Variable: MOUSE_DOWN
	 *
	 * Specifies the event name for mouseDown.
	 */
  MOUSE_DOWN: 'mouseDown',

  /**
	 * Variable: MOUSE_MOVE
	 *
	 * Specifies the event name for mouseMove.
	 */
  MOUSE_MOVE: 'mouseMove',

  /**
	 * Variable: MOUSE_UP
	 *
	 * Specifies the event name for mouseUp.
	 */
  MOUSE_UP: 'mouseUp',

  /**
	 * Variable: ACTIVATE
	 *
	 * Specifies the event name for activate.
	 */
  ACTIVATE: 'activate',

  /**
	 * Variable: RESIZE_START
	 *
	 * Specifies the event name for resizeStart.
	 */
  RESIZE_START: 'resizeStart',

  /**
	 * Variable: RESIZE
	 *
	 * Specifies the event name for resize.
	 */
  RESIZE: 'resize',

  /**
	 * Variable: RESIZE_END
	 *
	 * Specifies the event name for resizeEnd.
	 */
  RESIZE_END: 'resizeEnd',

  /**
	 * Variable: MOVE_START
	 *
	 * Specifies the event name for moveStart.
	 */
  MOVE_START: 'moveStart',

  /**
	 * Variable: MOVE
	 *
	 * Specifies the event name for move.
	 */
  MOVE: 'move',

  /**
	 * Variable: MOVE_END
	 *
	 * Specifies the event name for moveEnd.
	 */
  MOVE_END: 'moveEnd',

  /**
	 * Variable: PAN_START
	 *
	 * Specifies the event name for panStart.
	 */
  PAN_START: 'panStart',

  /**
	 * Variable: PAN
	 *
	 * Specifies the event name for pan.
	 */
  PAN: 'pan',

  /**
	 * Variable: PAN_END
	 *
	 * Specifies the event name for panEnd.
	 */
  PAN_END: 'panEnd',

  /**
	 * Variable: MINIMIZE
	 *
	 * Specifies the event name for minimize.
	 */
  MINIMIZE: 'minimize',

  /**
	 * Variable: NORMALIZE
	 *
	 * Specifies the event name for normalize.
	 */
  NORMALIZE: 'normalize',

  /**
	 * Variable: MAXIMIZE
	 *
	 * Specifies the event name for maximize.
	 */
  MAXIMIZE: 'maximize',

  /**
	 * Variable: HIDE
	 *
	 * Specifies the event name for hide.
	 */
  HIDE: 'hide',

  /**
	 * Variable: SHOW
	 *
	 * Specifies the event name for show.
	 */
  SHOW: 'show',

  /**
	 * Variable: CLOSE
	 *
	 * Specifies the event name for close.
	 */
  CLOSE: 'close',

  /**
	 * Variable: DESTROY
	 *
	 * Specifies the event name for destroy.
	 */
  DESTROY: 'destroy',

  /**
	 * Variable: REFRESH
	 *
	 * Specifies the event name for refresh.
	 */
  REFRESH: 'refresh',

  /**
	 * Variable: SIZE
	 *
	 * Specifies the event name for size.
	 */
  SIZE: 'size',

  /**
	 * Variable: SELECT
	 *
	 * Specifies the event name for select.
	 */
  SELECT: 'select',

  /**
	 * Variable: FIRED
	 *
	 * Specifies the event name for fired.
	 */
  FIRED: 'fired',

  /**
	 * Variable: FIRE_MOUSE_EVENT
	 *
	 * Specifies the event name for fireMouseEvent.
	 */
  FIRE_MOUSE_EVENT: 'fireMouseEvent',

  /**
	 * Variable: GESTURE
	 *
	 * Specifies the event name for gesture.
	 */
  GESTURE: 'gesture',

  /**
	 * Variable: TAP_AND_HOLD
	 *
	 * Specifies the event name for tapAndHold.
	 */
  TAP_AND_HOLD: 'tapAndHold',

  /**
	 * Variable: GET
	 *
	 * Specifies the event name for get.
	 */
  GET: 'get',

  /**
	 * Variable: RECEIVE
	 *
	 * Specifies the event name for receive.
	 */
  RECEIVE: 'receive',

  /**
	 * Variable: CONNECT
	 *
	 * Specifies the event name for connect.
	 */
  CONNECT: 'connect',

  /**
	 * Variable: DISCONNECT
	 *
	 * Specifies the event name for disconnect.
	 */
  DISCONNECT: 'disconnect',

  /**
	 * Variable: SUSPEND
	 *
	 * Specifies the event name for suspend.
	 */
  SUSPEND: 'suspend',

  /**
	 * Variable: RESUME
	 *
	 * Specifies the event name for suspend.
	 */
  RESUME: 'resume',

  /**
	 * Variable: MARK
	 *
	 * Specifies the event name for mark.
	 */
  MARK: 'mark',

  /**
	 * Variable: ROOT
	 *
	 * Specifies the event name for root.
	 */
  ROOT: 'root',

  /**
	 * Variable: POST
	 *
	 * Specifies the event name for post.
	 */
  POST: 'post',

  /**
	 * Variable: OPEN
	 *
	 * Specifies the event name for open.
	 */
  OPEN: 'open',

  /**
	 * Variable: SAVE
	 *
	 * Specifies the event name for open.
	 */
  SAVE: 'save',

  /**
	 * Variable: BEFORE_ADD_VERTEX
	 *
	 * Specifies the event name for beforeAddVertex.
	 */
  BEFORE_ADD_VERTEX: 'beforeAddVertex',

  /**
	 * Variable: ADD_VERTEX
	 *
	 * Specifies the event name for addVertex.
	 */
  ADD_VERTEX: 'addVertex',

  /**
	 * Variable: AFTER_ADD_VERTEX
	 *
	 * Specifies the event name for afterAddVertex.
	 */
  AFTER_ADD_VERTEX: 'afterAddVertex',

  /**
	 * Variable: DONE
	 *
	 * Specifies the event name for done.
	 */
  DONE: 'done',

  /**
	 * Variable: EXECUTE
	 *
	 * Specifies the event name for execute.
	 */
  EXECUTE: 'execute',

  /**
	 * Variable: EXECUTED
	 *
	 * Specifies the event name for executed.
	 */
  EXECUTED: 'executed',

  /**
	 * Variable: BEGIN_UPDATE
	 *
	 * Specifies the event name for beginUpdate.
	 */
  BEGIN_UPDATE: 'beginUpdate',

  /**
	 * Variable: START_EDIT
	 *
	 * Specifies the event name for startEdit.
	 */
  START_EDIT: 'startEdit',

  /**
	 * Variable: END_UPDATE
	 *
	 * Specifies the event name for endUpdate.
	 */
  END_UPDATE: 'endUpdate',

  /**
	 * Variable: END_EDIT
	 *
	 * Specifies the event name for endEdit.
	 */
  END_EDIT: 'endEdit',

  /**
	 * Variable: BEFORE_UNDO
	 *
	 * Specifies the event name for beforeUndo.
	 */
  BEFORE_UNDO: 'beforeUndo',

  /**
	 * Variable: UNDO
	 *
	 * Specifies the event name for undo.
	 */
  UNDO: 'undo',

  /**
	 * Variable: REDO
	 *
	 * Specifies the event name for redo.
	 */
  REDO: 'redo',

  /**
	 * Variable: CHANGE
	 *
	 * Specifies the event name for change.
	 */
  CHANGE: 'change',

  /**
	 * Variable: NOTIFY
	 *
	 * Specifies the event name for notify.
	 */
  NOTIFY: 'notify',

  /**
	 * Variable: LAYOUT_CELLS
	 *
	 * Specifies the event name for layoutCells.
	 */
  LAYOUT_CELLS: 'layoutCells',

  /**
	 * Variable: CLICK
	 *
	 * Specifies the event name for click.
	 */
  CLICK: 'click',

  /**
	 * Variable: SCALE
	 *
	 * Specifies the event name for scale.
	 */
  SCALE: 'scale',

  /**
	 * Variable: TRANSLATE
	 *
	 * Specifies the event name for translate.
	 */
  TRANSLATE: 'translate',

  /**
	 * Variable: SCALE_AND_TRANSLATE
	 *
	 * Specifies the event name for scaleAndTranslate.
	 */
  SCALE_AND_TRANSLATE: 'scaleAndTranslate',

  /**
	 * Variable: UP
	 *
	 * Specifies the event name for up.
	 */
  UP: 'up',

  /**
	 * Variable: DOWN
	 *
	 * Specifies the event name for down.
	 */
  DOWN: 'down',

  /**
	 * Variable: ADD
	 *
	 * Specifies the event name for add.
	 */
  ADD: 'add',

  /**
	 * Variable: REMOVE
	 *
	 * Specifies the event name for remove.
	 */
  REMOVE: 'remove',

  /**
	 * Variable: CLEAR
	 *
	 * Specifies the event name for clear.
	 */
  CLEAR: 'clear',

  /**
	 * Variable: ADD_CELLS
	 *
	 * Specifies the event name for addCells.
	 */
  ADD_CELLS: 'addCells',

  /**
	 * Variable: CELLS_ADDED
	 *
	 * Specifies the event name for cellsAdded.
	 */
  CELLS_ADDED: 'cellsAdded',

  /**
	 * Variable: MOVE_CELLS
	 *
	 * Specifies the event name for moveCells.
	 */
  MOVE_CELLS: 'moveCells',

  /**
	 * Variable: CELLS_MOVED
	 *
	 * Specifies the event name for cellsMoved.
	 */
  CELLS_MOVED: 'cellsMoved',

  /**
	 * Variable: RESIZE_CELLS
	 *
	 * Specifies the event name for resizeCells.
	 */
  RESIZE_CELLS: 'resizeCells',

  /**
	 * Variable: CELLS_RESIZED
	 *
	 * Specifies the event name for cellsResized.
	 */
  CELLS_RESIZED: 'cellsResized',

  /**
	 * Variable: TOGGLE_CELLS
	 *
	 * Specifies the event name for toggleCells.
	 */
  TOGGLE_CELLS: 'toggleCells',

  /**
	 * Variable: CELLS_TOGGLED
	 *
	 * Specifies the event name for cellsToggled.
	 */
  CELLS_TOGGLED: 'cellsToggled',

  /**
	 * Variable: ORDER_CELLS
	 *
	 * Specifies the event name for orderCells.
	 */
  ORDER_CELLS: 'orderCells',

  /**
	 * Variable: CELLS_ORDERED
	 *
	 * Specifies the event name for cellsOrdered.
	 */
  CELLS_ORDERED: 'cellsOrdered',

  /**
	 * Variable: REMOVE_CELLS
	 *
	 * Specifies the event name for removeCells.
	 */
  REMOVE_CELLS: 'removeCells',

  /**
	 * Variable: CELLS_REMOVED
	 *
	 * Specifies the event name for cellsRemoved.
	 */
  CELLS_REMOVED: 'cellsRemoved',

  /**
	 * Variable: GROUP_CELLS
	 *
	 * Specifies the event name for groupCells.
	 */
  GROUP_CELLS: 'groupCells',

  /**
	 * Variable: UNGROUP_CELLS
	 *
	 * Specifies the event name for ungroupCells.
	 */
  UNGROUP_CELLS: 'ungroupCells',

  /**
	 * Variable: REMOVE_CELLS_FROM_PARENT
	 *
	 * Specifies the event name for removeCellsFromParent.
	 */
  REMOVE_CELLS_FROM_PARENT: 'removeCellsFromParent',

  /**
	 * Variable: FOLD_CELLS
	 *
	 * Specifies the event name for foldCells.
	 */
  FOLD_CELLS: 'foldCells',

  /**
	 * Variable: CELLS_FOLDED
	 *
	 * Specifies the event name for cellsFolded.
	 */
  CELLS_FOLDED: 'cellsFolded',

  /**
	 * Variable: ALIGN_CELLS
	 *
	 * Specifies the event name for alignCells.
	 */
  ALIGN_CELLS: 'alignCells',

  /**
	 * Variable: LABEL_CHANGED
	 *
	 * Specifies the event name for labelChanged.
	 */
  LABEL_CHANGED: 'labelChanged',

  /**
	 * Variable: CONNECT_CELL
	 *
	 * Specifies the event name for connectCell.
	 */
  CONNECT_CELL: 'connectCell',

  /**
	 * Variable: CELL_CONNECTED
	 *
	 * Specifies the event name for cellConnected.
	 */
  CELL_CONNECTED: 'cellConnected',

  /**
	 * Variable: SPLIT_EDGE
	 *
	 * Specifies the event name for splitEdge.
	 */
  SPLIT_EDGE: 'splitEdge',

  /**
	 * Variable: FLIP_EDGE
	 *
	 * Specifies the event name for flipEdge.
	 */
  FLIP_EDGE: 'flipEdge',

  /**
	 * Variable: START_EDITING
	 *
	 * Specifies the event name for startEditing.
	 */
  START_EDITING: 'startEditing',

  /**
	 * Variable: EDITING_STARTED
	 *
	 * Specifies the event name for editingStarted.
	 */
  EDITING_STARTED: 'editingStarted',

  /**
	 * Variable: EDITING_STOPPED
	 *
	 * Specifies the event name for editingStopped.
	 */
  EDITING_STOPPED: 'editingStopped',

  /**
	 * Variable: ADD_OVERLAY
	 *
	 * Specifies the event name for addOverlay.
	 */
  ADD_OVERLAY: 'addOverlay',

  /**
	 * Variable: REMOVE_OVERLAY
	 *
	 * Specifies the event name for removeOverlay.
	 */
  REMOVE_OVERLAY: 'removeOverlay',

  /**
	 * Variable: UPDATE_CELL_SIZE
	 *
	 * Specifies the event name for updateCellSize.
	 */
  UPDATE_CELL_SIZE: 'updateCellSize',

  /**
	 * Variable: ESCAPE
	 *
	 * Specifies the event name for escape.
	 */
  ESCAPE: 'escape',

  /**
	 * Variable: DOUBLE_CLICK
	 *
	 * Specifies the event name for doubleClick.
	 */
  DOUBLE_CLICK: 'doubleClick',

  /**
	 * Variable: START
	 *
	 * Specifies the event name for start.
	 */
  START: 'start',

  /**
	 * Variable: RESET
	 *
	 * Specifies the event name for reset.
	 */
  RESET: 'reset'

}
